﻿using Delphi.Isis.EodServiceReference;
using Knapcode.TorSharp;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.ServiceModel;

namespace Delphi.Isis.ServiceClients {
    public class EodServiceClient {
        private DataSoapClient _dataSoapClient;
        private static EodServiceClient _eodServiceClient;
        private LOGINRESPONSE _loginResponse;

        private string Username { set; get; }
        private string Password { set; get; }

        public async void TorTest() {
            var settings = new TorSharpSettings {
                ZippedToolsDirectory = Path.Combine(Path.GetTempPath(), "TorZipped"),
                ExtractedToolsDirectory = Path.Combine(Path.GetTempPath(), "TorExtracted"),
                PrivoxyPort = 1337,
                TorSocksPort = 1338,
                TorControlPort = 1339,
                TorControlPassword = "foobar"
            };

            // download tools
            await new TorSharpToolFetcher(settings, new HttpClient()).FetchAsync();

            // execute
            var proxy = new TorSharpProxy(settings);
            var handler = new HttpClientHandler {
                Proxy = new WebProxy(new Uri("http://localhost:" + settings.PrivoxyPort))
            };
            var httpClient = new HttpClient(handler);
            await proxy.ConfigureAndStartAsync();
            //Console.WriteLine(await httpClient.GetStringAsync("http://icanhazip.com"));
            await proxy.GetNewIdentityAsync();
            //Console.WriteLine(await httpClient.GetStringAsync("http://icanhazip.com"));

            Console.WriteLine("Get some data....");
            QUOTE[] e = Quotes("NYSE", new DateTime(2016, 3, 18), "1");
            Console.WriteLine("-----------------------------------------------------");
            Console.WriteLine(e.Length);
            Console.WriteLine("-----------------------------------------------------");

            proxy.Stop();
        }

        private EodServiceClient(string username, string password) {
            _dataSoapClient = CreateWebServiceInstance();

            Username = username;
            Password = password;

            bool ret = Login();
            int counter = 0;

            // if login was not succesfull, give it another try.
            if (!ret) {
                do {
                    System.Threading.Thread.Sleep(1000);
                    ret = Login();
                    ++counter;
                    if (counter > 2) {
                        break;
                    }
                } while (!ret);
            }
            if (!ret) {
                throw new Exception();
            }
        }

        public static EodServiceClient GetInstance(string username, string password) {
            if (_eodServiceClient == null) {
                _eodServiceClient = new EodServiceClient(username, password);
            }
            return _eodServiceClient;
        }

        internal static DataSoapClient CreateWebServiceInstance() {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.MaxReceivedMessageSize = 2147483647;
            binding.SendTimeout = TimeSpan.FromMinutes(60);
            binding.OpenTimeout = TimeSpan.FromMinutes(60);
            binding.CloseTimeout = TimeSpan.FromMinutes(60);
            binding.ReceiveTimeout = TimeSpan.FromMinutes(60);

            return new DataSoapClient(binding, new EndpointAddress("http://ws.eoddata.com/data.asmx"));
        }

        private bool Login() {
            // check whether already logged in
            if(_loginResponse != null) {
                return true;
            } 

            // Login with webservice
            try {
                _loginResponse = _dataSoapClient.Login(Username, Password);
            } catch (Exception) {
                _loginResponse = null;
                return false;
            }

            // check return message from webservice
            if (String.Equals("Login Successful", _loginResponse.Message) && _loginResponse.Token != null) {
                return true;
            }

            // Hmm, something has gone wrong....
            _loginResponse = null;
            return false;
        }

        public EXCHANGE[] Exchanges() {
            RESPONSE resp = _dataSoapClient.ExchangeList(_loginResponse.Token);
            if (String.Equals("Success", resp.Message)) {
                return resp.EXCHANGES;
            }
            return null;
        }

        public SYMBOL[] Symbols(string exchangeCode) {
            RESPONSE resp = _dataSoapClient.SymbolList(_loginResponse.Token, exchangeCode);
            if (String.Equals("Success", resp.Message)) {
                return resp.SYMBOLS;
            }
            return null;
        }

        public QUOTE[] Quotes(string exchangeCode) {
            RESPONSE resp = _dataSoapClient.QuoteList(_loginResponse.Token, exchangeCode);
            if (String.Equals("Success", resp.Message)) {
                return resp.QUOTES;
            }
            return null;
        }

        public QUOTE[] Quotes(string exchangeCode, DateTime tradeDate, string period) {
            RESPONSE resp = _dataSoapClient.QuoteListByDatePeriod(_loginResponse.Token, exchangeCode, tradeDate.ToString("yyyyMMdd"), period);
            if (String.Equals("Success", resp.Message)) {
                return resp.QUOTES;
            }
            return null;
        }

        public SYMBOLCHANGE[] SymbolChanges(string exchangeCode) {
            RESPONSE resp = _dataSoapClient.SymbolChangesByExchange(_loginResponse.Token, exchangeCode);
            if (String.Equals("Success", resp.Message)) {
                return resp.SYMBOLCHANGES;
            }
            return null;
        }

        public SPLIT[] SymbolSplits(string exchangeCode) {
            RESPONSE resp = _dataSoapClient.SplitListByExchange(_loginResponse.Token, exchangeCode);
            if (String.Equals("Success", resp.Message)) {
                return resp.SPLITS;
            }
            return null;
        }

        public FUNDAMENTAL[] Fundamentals(string exchangeCode) {
            RESPONSE resp = _dataSoapClient.FundamentalList(_loginResponse.Token, exchangeCode);
            if (String.Equals("Success", resp.Message)) {
                return resp.FUNDAMENTALS;
            }
            return null;
        }
    }
}
